import os
import win32com.client as win32
import psutil
import time

#版本号
ver = '1.0.0'
#作者
author='justin zhou'

#函数库
#退出word
def quitWord():
    #不保存退出
    doc_app.Quit(SaveChanges=False)
    try:
        pl = psutil.pids()
        for pid in pl:
            if (psutil.Process(pid).name().find("WINWORD.EXE") > 0):
                if isinstance(pid, int):
                    print("正在结束进程[%s],PID为[%s]" % (psutil.Process(pid).name(), pid))
                    process = psutil.Process(pid)
                    process.terminate()
    except Exception as e:
        print("结束失败，请手动使用任务管理器结束Word程序")

#关闭word文档
def closeDoc():
    doc.Close()

#全部替换
def replaceAll(oldStr,newStr):
    #替换页眉
    header = doc.Sections(1).Headers(1).Range.Find
    header.ClearFormatting()
    header.Text = oldStr
    header.Replacement.ClearFormatting()
    header.Replacement.Text = newStr
    header.Execute(Replace=win32.constants.wdReplaceAll)
    #替换页脚
    footer = doc.Sections(1).Footers(1).Range.Find
    footer.ClearFormatting()
    footer.Text = oldStr
    footer.Replacement.ClearFormatting()
    footer.Replacement.Text = newStr
    footer.Execute(Replace=win32.constants.wdReplaceAll)
    # 正文
    find_obj = doc_app.Selection.Find
    find_obj.ClearFormatting()
    find_obj.Text = oldStr
    find_obj.Replacement.ClearFormatting()
    find_obj.Replacement.Text = newStr
    find_obj.Execute(Replace=win32.constants.wdReplaceAll)

#保存文件
def save(path,name,filename):
    doc.SaveAs(path + name + "\\" + filename)

#批量替换word
print("感谢使用Word批量替换 - 版本:v%s" %(ver))
print("将替换本目录下所有的doc和docx文件")
print("为防止误操作，请输入ok确认")
command=input("确认：")
if command.lower()!="ok":
    input("程序终止，按回车键退出")
    exit()

print("正在读取目录文件列表")
#当前路径
path=os.getcwd()+'\\'
dirs=os.listdir(path)
index=1
#待处理文件列表
fileList = []
for file in dirs:
    if os.path.isfile(path + file):
        filename, type = os.path.splitext(path + file)
        index = index + 1
        if (type == '.doc' or type == '.docx'):
            #过滤word打开时的隐藏文件
            if (filename.find("~$")==-1):
                fileList.append(path + file)

if len(fileList)==0:
    print("本文件夹内无word文档，无法执行替换")
    input("程序终止，按回车键退出")
    exit()

fileNum = len(fileList)

index = 1
for file in fileList:
    print("%d、%s" %(index,file))
    index = index + 1

print("请确认要替换上述文件，共%d个" %(len(fileList)))
input("按回车继续下一步")

findStr = ""
print("请输入要查找的文字")
while findStr=='':
    findStr = input("查找文字：")
    if findStr == '':
        print("**查找的文字不能为空**")


replaceStr = ""
print("请输入要替换的文字，多个请用,分割")
while replaceStr=='':
    replaceStr = input("替换文字：")
    if replaceStr == '':
        print("**替换的文字不能为空**")
    # 替换中文逗号，以防输入错误
    replaceList = replaceStr.replace('，', ',').strip(',').split(',')
    if (len(replaceList)!=len(set(replaceList))):
        print("**替换的文字不能重复**")
        replaceStr=""

total = fileNum * len(replaceList)

print("是否有备用替换，有的话请输入y，直接回车不替换")
isSpare=input("命令:")
if isSpare.lower()=="y":
    #查找备用
    findSpare=""
    #替换备用
    replaceSpare=""
    doNext=True
    while doNext:
        findSpare = input("请输入备用查找的字符：")
        if findSpare=='':
            print("**备用查找的字符不能为空**")
            continue
        print("备用替换的字符，需要和替换的文字一一对应，用,分割")
        replaceSpare = input("请输入备用替换的字符：")
        if replaceSpare=='':
            print("**备用替换的字符不能为空**")
            continue
        replaceSpareList = replaceSpare.replace('，', ',').strip(',').split(',')
        if len(replaceList)!=len(replaceSpareList):
            print("**备用替换的字符数量和替换字符数量不一致**")
            continue

        doNext =False

print("%d个文件，需要替换%d个方案，共%d个文件任务" %(fileNum,len(replaceList),total))
print("任务列表：")
index = 1
for item in replaceList:
    print("%d、%s -> %s" %(index,findStr,item))
    index = index + 1

print("准备完毕，按回车键开始任务")
input("按回车开始")

#记录开始时间
startTime=time.time()

#创建文件夹
for item in replaceList:
    if os.path.exists(path + item) == False:
        os.mkdir(item)

# 打开word应用程序
doc_app = win32.gencache.EnsureDispatch('Word.Application')

#当前进行的任务
currentIndex = 1
#上一个字符
lastReplaceStr=""

try:
    for item in fileList:
        filename = os.path.basename(item)
        print("正在执行替换任务：文件 %s" %(filename))
        doc = doc_app.Documents.Open(item)
        #隐藏word界面
        doc_app.Visible = False
        lastReplaceStr = findStr
        if isSpare.lower()=="y":
            lastSpareStr = findSpare
        replaceIndex = 0
        for item1 in replaceList:
            alreadySpend = time.time() - startTime
            currentSpeed = round(currentIndex / alreadySpend,2)
            print("任务进度：%d/%d (%d%%) 速度:%d个/s 预计%d秒后完成" %(currentIndex,total,round((currentIndex/total)*100,2),currentSpeed,round((total-currentIndex)/currentSpeed,1)+1))
            print("正在执行替换: %s => %s" % (findStr,item1))
            replaceAll(lastReplaceStr,item1)
            if isSpare.lower()=="y":
                print("正在执行替换: %s => %s" % (findSpare, replaceSpareList[replaceIndex]))
                replaceAll(lastSpareStr, replaceSpareList[replaceIndex])
                lastSpareStr = replaceSpareList[replaceIndex]
            save(path,item1,filename)
            lastReplaceStr = item1
            currentIndex = currentIndex + 1
            replaceIndex = replaceIndex + 1

        #关闭当前文档
        closeDoc()
    #退出word
    quitWord()
except Exception as e:
    print("发生错误：%s" %(e))
    print("任务已退出")
    # 退出word
    quitWord()

#结束时间
endTime=time.time()
#花费时间
spend = endTime-startTime
print ("-------------------------------")
print ("文件总数：%d 个" %(total))
print ("累计耗时：%d 秒" %(spend))
print ("平均速度：%d 个/秒" %(round((total/spend),2)))
input("任务执行完毕，回车退出")














